package com.example.smartpark.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartpark.dto.ParkingSpaceAddDTO;
import com.example.smartpark.dto.ParkingSpaceUpdateDTO;
import com.example.smartpark.exception.BusinessException;
import com.example.smartpark.mapper.ParkingSpaceMapper;
import com.example.smartpark.model.ParkingLot;
import com.example.smartpark.model.ParkingSpace;
import com.example.smartpark.service.ParkingLotService;
import com.example.smartpark.service.ParkingSpaceService;
import com.example.smartpark.vo.ParkingSpaceVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 车位服务实现类
 */
@Slf4j
@Service
public class ParkingSpaceServiceImpl extends ServiceImpl<ParkingSpaceMapper, ParkingSpace> implements ParkingSpaceService {

    @Autowired
    private ParkingLotService parkingLotService;

    /**
     * 车位类型名称映射
     */
    private static final String[] SPACE_TYPE_NAMES = {"普通", "固定", "访客"};

    /**
     * 车位状态名称映射
     */
    private static final String[] SPACE_STATUS_NAMES = {"空闲", "占用", "维护", "预约"};

    /**
     * 分页获取车位列表
     *
     * @param page 页码
     * @param size 每页数量
     * @param parkingLotId 停车场ID（可选）
     * @param spaceNumber 车位编号（可选）
     * @param area 所在区域（可选）
     * @param status 状态（可选）
     * @return 分页车位列表
     */
    @Override
    public IPage<ParkingSpaceVO> getParkingSpacePage(int page, int size, Integer parkingLotId, String spaceNumber, String area, Integer status) {
        log.info("分页获取车位列表: page={}, size={}, parkingLotId={}, spaceNumber={}, area={}, status={}", 
                page, size, parkingLotId, spaceNumber, area, status);
        
        // 构建查询条件
        LambdaQueryWrapper<ParkingSpace> queryWrapper = new LambdaQueryWrapper<>();
        
        // 根据停车场ID查询
        if (parkingLotId != null) {
            queryWrapper.eq(ParkingSpace::getParkingLotId, parkingLotId);
        }
        
        // 根据车位编号模糊查询
        if (StringUtils.hasText(spaceNumber)) {
            queryWrapper.like(ParkingSpace::getSpaceNumber, spaceNumber);
        }
        
        // 根据所在区域查询
        if (StringUtils.hasText(area)) {
            queryWrapper.eq(ParkingSpace::getArea, area);
        }
        
        // 根据状态查询
        if (status != null) {
            queryWrapper.eq(ParkingSpace::getStatus, status);
        }
        
        // 按创建时间降序排序
        queryWrapper.orderByDesc(ParkingSpace::getCreatedAt);
        
        // 分页查询
        Page<ParkingSpace> pageParam = new Page<>(page, size);
        IPage<ParkingSpace> parkingSpacePage = page(pageParam, queryWrapper);
        
        // 转换为VO对象
        IPage<ParkingSpaceVO> voPage = parkingSpacePage.convert(this::convertToVO);
        
        // 填充停车场名称和状态名称
        fillParkingLotNames(voPage.getRecords());
        
        return voPage;
    }

    /**
     * 获取车位详情
     *
     * @param id 车位ID
     * @return 车位详情
     */
    @Override
    public ParkingSpaceVO getParkingSpaceById(Integer id) {
        log.info("获取车位详情: id={}", id);
        
        ParkingSpace parkingSpace = getById(id);
        if (parkingSpace == null) {
            throw new BusinessException("车位不存在");
        }
        
        ParkingSpaceVO parkingSpaceVO = convertToVO(parkingSpace);
        
        // 填充停车场名称
        ParkingLot parkingLot = parkingLotService.getById(parkingSpace.getParkingLotId());
        if (parkingLot != null) {
            parkingSpaceVO.setParkingLotName(parkingLot.getName());
        }
        
        return parkingSpaceVO;
    }

    /**
     * 根据停车场ID获取所有车位
     *
     * @param parkingLotId 停车场ID
     * @return 车位列表
     */
    @Override
    public List<ParkingSpaceVO> getParkingSpacesByLotId(Integer parkingLotId) {
        log.info("根据停车场ID获取所有车位: parkingLotId={}", parkingLotId);
        
        // 检查停车场是否存在
        ParkingLot parkingLot = parkingLotService.getById(parkingLotId);
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        // 查询车位列表
        LambdaQueryWrapper<ParkingSpace> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkingSpace::getParkingLotId, parkingLotId);
        queryWrapper.orderByAsc(ParkingSpace::getArea).orderByAsc(ParkingSpace::getSpaceNumber);
        
        List<ParkingSpace> parkingSpaces = list(queryWrapper);
        
        // 转换为VO对象
        List<ParkingSpaceVO> parkingSpaceVOs = parkingSpaces.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        // 填充停车场名称
        for (ParkingSpaceVO parkingSpaceVO : parkingSpaceVOs) {
            parkingSpaceVO.setParkingLotName(parkingLot.getName());
        }
        
        return parkingSpaceVOs;
    }

    /**
     * 添加车位
     *
     * @param parkingSpaceAddDTO 添加车位DTO
     * @return 添加的车位信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ParkingSpaceVO addParkingSpace(ParkingSpaceAddDTO parkingSpaceAddDTO) {
        log.info("添加车位: parkingSpaceAddDTO={}", parkingSpaceAddDTO);
        
        // 检查停车场是否存在
        ParkingLot parkingLot = parkingLotService.getById(parkingSpaceAddDTO.getParkingLotId());
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        // 检查车位编号是否已存在
        if (checkSpaceNumberExists(parkingSpaceAddDTO.getParkingLotId(), parkingSpaceAddDTO.getSpaceNumber(), null)) {
            throw new BusinessException("车位编号已存在");
        }
        
        // 创建车位对象
        ParkingSpace parkingSpace = new ParkingSpace();
        BeanUtils.copyProperties(parkingSpaceAddDTO, parkingSpace);
        
        // 保存车位信息
        boolean success = save(parkingSpace);
        if (!success) {
            throw new BusinessException("添加车位失败");
        }
        
        // 如果新增的是空闲车位，更新停车场可用车位数
        if (parkingSpace.getStatus() == 0) {
            parkingLotService.updateAvailableSpaces(parkingSpace.getParkingLotId());
        }
        
        // 转换为VO对象
        ParkingSpaceVO parkingSpaceVO = convertToVO(parkingSpace);
        parkingSpaceVO.setParkingLotName(parkingLot.getName());
        
        return parkingSpaceVO;
    }

    /**
     * 更新车位信息
     *
     * @param id 车位ID
     * @param parkingSpaceUpdateDTO 更新车位DTO
     * @return 更新后的车位信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ParkingSpaceVO updateParkingSpace(Integer id, ParkingSpaceUpdateDTO parkingSpaceUpdateDTO) {
        log.info("更新车位: id={}, parkingSpaceUpdateDTO={}", id, parkingSpaceUpdateDTO);
        
        // 获取车位信息
        ParkingSpace parkingSpace = getById(id);
        if (parkingSpace == null) {
            throw new BusinessException("车位不存在");
        }
        
        // 检查车位编号是否已存在
        if (parkingSpaceUpdateDTO.getSpaceNumber() != null && 
            !parkingSpaceUpdateDTO.getSpaceNumber().equals(parkingSpace.getSpaceNumber()) && 
            checkSpaceNumberExists(parkingSpace.getParkingLotId(), parkingSpaceUpdateDTO.getSpaceNumber(), id)) {
            throw new BusinessException("车位编号已存在");
        }
        
        // 记录原状态
        Integer oldStatus = parkingSpace.getStatus();
        
        // 更新车位信息
        boolean needsUpdate = false;
        
        if (parkingSpaceUpdateDTO.getSpaceNumber() != null && !parkingSpaceUpdateDTO.getSpaceNumber().equals(parkingSpace.getSpaceNumber())) {
            parkingSpace.setSpaceNumber(parkingSpaceUpdateDTO.getSpaceNumber());
            needsUpdate = true;
        }
        
        if (parkingSpaceUpdateDTO.getSpaceType() != null && !parkingSpaceUpdateDTO.getSpaceType().equals(parkingSpace.getSpaceType())) {
            parkingSpace.setSpaceType(parkingSpaceUpdateDTO.getSpaceType());
            needsUpdate = true;
        }
        
        if (parkingSpaceUpdateDTO.getArea() != null && !parkingSpaceUpdateDTO.getArea().equals(parkingSpace.getArea())) {
            parkingSpace.setArea(parkingSpaceUpdateDTO.getArea());
            needsUpdate = true;
        }
        
        if (parkingSpaceUpdateDTO.getFloor() != null && !parkingSpaceUpdateDTO.getFloor().equals(parkingSpace.getFloor())) {
            parkingSpace.setFloor(parkingSpaceUpdateDTO.getFloor());
            needsUpdate = true;
        }
        
        if (parkingSpaceUpdateDTO.getStatus() != null && !parkingSpaceUpdateDTO.getStatus().equals(parkingSpace.getStatus())) {
            parkingSpace.setStatus(parkingSpaceUpdateDTO.getStatus());
            needsUpdate = true;
        }
        
        if (parkingSpaceUpdateDTO.getPositionX() != null && !parkingSpaceUpdateDTO.getPositionX().equals(parkingSpace.getPositionX())) {
            parkingSpace.setPositionX(parkingSpaceUpdateDTO.getPositionX());
            needsUpdate = true;
        }
        
        if (parkingSpaceUpdateDTO.getPositionY() != null && !parkingSpaceUpdateDTO.getPositionY().equals(parkingSpace.getPositionY())) {
            parkingSpace.setPositionY(parkingSpaceUpdateDTO.getPositionY());
            needsUpdate = true;
        }
        
        // 更新车位信息
        if (needsUpdate) {
            boolean success = updateById(parkingSpace);
            if (!success) {
                throw new BusinessException("更新车位信息失败");
            }
            
            // 如果状态发生变化，更新停车场可用车位数
            if (parkingSpaceUpdateDTO.getStatus() != null && !parkingSpaceUpdateDTO.getStatus().equals(oldStatus)) {
                parkingLotService.updateAvailableSpaces(parkingSpace.getParkingLotId());
            }
        }
        
        // 转换为VO对象
        ParkingSpaceVO parkingSpaceVO = convertToVO(parkingSpace);
        
        // 填充停车场名称
        ParkingLot parkingLot = parkingLotService.getById(parkingSpace.getParkingLotId());
        if (parkingLot != null) {
            parkingSpaceVO.setParkingLotName(parkingLot.getName());
        }
        
        return parkingSpaceVO;
    }

    /**
     * 删除车位
     *
     * @param id 车位ID
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteParkingSpace(Integer id) {
        log.info("删除车位: id={}", id);
        
        // 获取车位信息
        ParkingSpace parkingSpace = getById(id);
        if (parkingSpace == null) {
            throw new BusinessException("车位不存在");
        }
        
        // TODO: 检查车位是否有相关的停车记录、预约记录等数据
        
        // 记录停车场ID和状态
        Integer parkingLotId = parkingSpace.getParkingLotId();
        Integer status = parkingSpace.getStatus();
        
        // 删除车位
        boolean success = removeById(id);
        
        // 如果删除的是空闲车位，更新停车场可用车位数
        if (success && status == 0) {
            parkingLotService.updateAvailableSpaces(parkingLotId);
        }
        
        return success;
    }

    /**
     * 检查车位编号是否已存在于指定停车场
     *
     * @param parkingLotId 停车场ID
     * @param spaceNumber 车位编号
     * @param excludeId 排除的车位ID（用于更新时）
     * @return 是否存在
     */
    @Override
    public boolean checkSpaceNumberExists(Integer parkingLotId, String spaceNumber, Integer excludeId) {
        log.info("检查车位编号是否已存在: parkingLotId={}, spaceNumber={}, excludeId={}", parkingLotId, spaceNumber, excludeId);
        
        // 构建查询条件
        LambdaQueryWrapper<ParkingSpace> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkingSpace::getParkingLotId, parkingLotId)
                    .eq(ParkingSpace::getSpaceNumber, spaceNumber);
        
        // 排除当前车位
        if (excludeId != null) {
            queryWrapper.ne(ParkingSpace::getId, excludeId);
        }
        
        return count(queryWrapper) > 0;
    }

    /**
     * 批量添加车位
     *
     * @param parkingLotId 停车场ID
     * @param prefix 车位编号前缀
     * @param startNumber 起始编号
     * @param count 车位数量
     * @param spaceType 车位类型
     * @param area 所在区域
     * @param floor 所在楼层
     * @return 添加的车位列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ParkingSpaceVO> batchAddParkingSpaces(Integer parkingLotId, String prefix, Integer startNumber, Integer count,
                                                   Integer spaceType, String area, String floor) {
        log.info("批量添加车位: parkingLotId={}, prefix={}, startNumber={}, count={}, spaceType={}, area={}, floor={}",
                parkingLotId, prefix, startNumber, count, spaceType, area, floor);
        
        // 检查停车场是否存在
        ParkingLot parkingLot = parkingLotService.getById(parkingLotId);
        if (parkingLot == null) {
            throw new BusinessException("停车场不存在");
        }
        
        // 创建车位对象列表
        List<ParkingSpace> parkingSpaces = new ArrayList<>();
        
        for (int i = 0; i < count; i++) {
            String spaceNumber = prefix + (startNumber + i);
            
            // 检查车位编号是否已存在
            if (checkSpaceNumberExists(parkingLotId, spaceNumber, null)) {
                throw new BusinessException("车位编号 " + spaceNumber + " 已存在");
            }
            
            // 创建车位对象
            ParkingSpace parkingSpace = new ParkingSpace();
            parkingSpace.setParkingLotId(parkingLotId);
            parkingSpace.setSpaceNumber(spaceNumber);
            parkingSpace.setSpaceType(spaceType);
            parkingSpace.setArea(area);
            parkingSpace.setFloor(floor);
            parkingSpace.setStatus(0); // 默认为空闲状态
            
            parkingSpaces.add(parkingSpace);
        }
        
        // 批量保存车位信息
        boolean success = saveBatch(parkingSpaces);
        if (!success) {
            throw new BusinessException("批量添加车位失败");
        }
        
        // 更新停车场可用车位数
        parkingLotService.updateAvailableSpaces(parkingLotId);
        
        // 转换为VO对象
        List<ParkingSpaceVO> parkingSpaceVOs = parkingSpaces.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        // 填充停车场名称
        for (ParkingSpaceVO parkingSpaceVO : parkingSpaceVOs) {
            parkingSpaceVO.setParkingLotName(parkingLot.getName());
        }
        
        return parkingSpaceVOs;
    }

    /**
     * 将ParkingSpace对象转换为ParkingSpaceVO对象
     *
     * @param parkingSpace ParkingSpace对象
     * @return ParkingSpaceVO对象
     */
    private ParkingSpaceVO convertToVO(ParkingSpace parkingSpace) {
        if (parkingSpace == null) {
            return null;
        }
        
        ParkingSpaceVO parkingSpaceVO = new ParkingSpaceVO();
        BeanUtils.copyProperties(parkingSpace, parkingSpaceVO);
        
        // 设置车位类型名称
        if (parkingSpace.getSpaceType() != null && parkingSpace.getSpaceType() >= 0 && parkingSpace.getSpaceType() < SPACE_TYPE_NAMES.length) {
            parkingSpaceVO.setSpaceTypeName(SPACE_TYPE_NAMES[parkingSpace.getSpaceType()]);
        }
        
        // 设置车位状态名称
        if (parkingSpace.getStatus() != null && parkingSpace.getStatus() >= 0 && parkingSpace.getStatus() < SPACE_STATUS_NAMES.length) {
            parkingSpaceVO.setStatusName(SPACE_STATUS_NAMES[parkingSpace.getStatus()]);
        }
        
        return parkingSpaceVO;
    }

    /**
     * 填充停车场名称
     *
     * @param parkingSpaceVOs 车位VO列表
     */
    private void fillParkingLotNames(List<ParkingSpaceVO> parkingSpaceVOs) {
        if (parkingSpaceVOs == null || parkingSpaceVOs.isEmpty()) {
            return;
        }
        
        // 获取所有涉及的停车场ID
        List<Integer> parkingLotIds = parkingSpaceVOs.stream()
                .map(ParkingSpaceVO::getParkingLotId)
                .distinct()
                .collect(Collectors.toList());
        
        // 查询所有相关的停车场
        List<ParkingLot> parkingLots = parkingLotService.listByIds(parkingLotIds);
        
        // 构建停车场ID到名称的映射
        java.util.Map<Integer, String> parkingLotNames = parkingLots.stream()
                .collect(Collectors.toMap(ParkingLot::getId, ParkingLot::getName));
        
        // 填充停车场名称
        for (ParkingSpaceVO parkingSpaceVO : parkingSpaceVOs) {
            parkingSpaceVO.setParkingLotName(parkingLotNames.get(parkingSpaceVO.getParkingLotId()));
        }
    }
} 